package top.kiterunner.learning.codeoffer_solution;

//题目：设计一个类，我们只能生成该类的一个实例

/**
 * AdorynZhao in Tencent-UESTC.
 * Source Code Created on 2017/6/29.
 */
public class C2_Singleton {

    /**
     * 单例模式，懒汉式，线程安全
     */
    public static class Singleton1 {
        private final static Singleton1 INSTANCE = new Singleton1();

        private Singleton1() {

        }

        public static Singleton1 getInstance() {
            return INSTANCE;
        }
    }

    /**
     * 单例模式，饿汉式，线程不安全
     */
    public static class Singleton2 {
        private static Singleton2 INSTANCE = null;

        private Singleton2() {

        }

        public static Singleton2 getInstance() {
            if (INSTANCE == null) {
                INSTANCE = new Singleton2();
            }

            return INSTANCE;
        }
    }

    /**
     * 单例模式，饿汉式，线程安全，多线程
     */
    public static class Singleton3 {
        private static Singleton3 INSTANCE = null;

        private Singleton3() {

        }

        public static synchronized Singleton3 getInstance() {
            if (INSTANCE == null) {
                INSTANCE = new Singleton3();
            }

            return INSTANCE;
        }
    }

    /**
      * 单例模式，饿汉式，变种，线程安全
      */
    public static class Singleton4 {
        private static Singleton4 INSTANCE = null;

        static {
            INSTANCE = new Singleton4();
        }

        private Singleton4() {

        }

        public static Singleton4 getInstance() {
            return INSTANCE;
        }
    }

    /**
     * 单例模式，懒汉式，使用静态内部类，线程安全【推荐】
     */
    public static class Singleton5 {

        // 静态内部类在第一次使用该静态内部类时进行类加载过程
        private final static class SingletonHolder {
            private final static Singleton5 INSTANCE = new Singleton5();
        }

        private Singleton5() {

        }

        public static Singleton5 getInstance() {
            return SingletonHolder.INSTANCE;
        }
    }

    /**
     * 单例模式，使用双重锁检查机制
     */
    public static class Singleton6 {
        private volatile static Singleton6 INSTANCE = null;

        private Singleton6() {

        }

        public static Singleton6 getInstance() {
            if (INSTANCE == null) {
                synchronized (Singleton6.class) {
                    if (INSTANCE == null) {
                        INSTANCE = new Singleton6();
                    }
                }
            }

            return INSTANCE;
        }
    }

    public static void main(String[] args) {
        System.out.println(Singleton1.getInstance() == Singleton1.getInstance());
        System.out.println(Singleton2.getInstance() == Singleton2.getInstance());
        System.out.println(Singleton3.getInstance() == Singleton3.getInstance());
        System.out.println(Singleton4.getInstance() == Singleton4.getInstance());
        System.out.println(Singleton5.getInstance() == Singleton5.getInstance());
        System.out.println(Singleton6.getInstance() == Singleton6.getInstance());
    }
}
